package com.example.train.common.config.security.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.train.common.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * JwtToken生成的工具类
 * JWT token的格式：header.payload.signature
 * header的格式（算法、token的类型）：
 * {"alg": "HS512","typ": "JWT"}
 * payload的格式（用户名、创建时间、生成时间）：
 * {"sub":"wang","created":1489079981393,"exp":1489684781}
 * signature的生成算法：
 * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
 */
@Component
@Slf4j
public class JwtTokenUtil {

    @Autowired
    private AESUtil aesUtil;

    @Value("${jwt.expiration}")
    private Long expiration;
    @Value("${jwt.tokenHead}")
    private String tokenHead;

    /**
     * 根据负责生成JWT的token
     *
     * 加入payload
     */
    public String generateToken(String username,String salt) {
        Algorithm algorithm = Algorithm.HMAC256(salt);

        String usernameEncryptStr = aesUtil.encrypt(username);
        log.debug("usernameEncryptStr:"+usernameEncryptStr);

        return tokenHead + JWT.create()
                //主题
                .withSubject(usernameEncryptStr)
                .withExpiresAt(generateExpirationDate())
                //发布时间
                .withIssuedAt(new Date())
                .sign(algorithm);
    }

    public DecodedJWT decode(String token){
        return JWT.decode(token);
    }

    public String getUserFromToken(DecodedJWT decodedJWT){
        return aesUtil.decrypt(decodedJWT.getSubject());
    }

    public String getUserFromToken(String token){
        String usernameEncrypt = JWT.decode(token).getSubject();
        return aesUtil.decrypt(usernameEncrypt);
    }

    public DecodedJWT verifyJwtToken(String salt, String token){
        Algorithm algorithm = Algorithm.HMAC256(salt);
        JWTVerifier verifier = JWT.require(algorithm)
                .build();
        return verifier.verify(token);
    }

    /**
     * 判断token是否已经失效
     */
    public boolean isTokenExpired(String token) {
        Date expiredDate = JWT.decode(token).getExpiresAt();
        return expiredDate.before(new Date());
    }

    /**
     * 判断token是否已经失效
     */
    public boolean isTokenExpired(DecodedJWT decodedJWT) {
        Date expiredDate = decodedJWT.getExpiresAt();
        return expiredDate.before(new Date());
    }

    /**
     * 生成token的过期时间
     */
    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis() + expiration * 1000);
    }

    /**
     * 判断token是否可以被刷新
     */
    public boolean canRefresh(String token) {
        return !isTokenExpired(token);
    }
}
